HAL MMC initialization and configuration functions migration

The goal of this page is to show how to migrate the initialization sequence using STM32CubeMX2:

  • Open STM32CubeMX2 MMC configuration panel.

  • Configure the SW layer HAL.

  • Configure the MMC main features.

  • Configure the advanced MMC features.

  • Configure the MMC security and privilege features if needed.

  • Configure the MMC GPIO pins.

  • Configure the NVIC if the application requires the MMC to be used in IT mode.

  • Generate the code.

HAL MMC configuration panel

Create a new project with STM32CubeMX2, start by enabling the SDMMC1 instance as MMC, as shown in this example with the selected SDMMC1, then start the initialization and the main configuration.

Project configuration panel

HAL MMC main features configuration

The bus width and transfer frequency are selected according to the MMC card and SDMMC capabilities. The Clock Edge, Clock Power Save, and Hardware Flow Control options can be configured as needed. User can either choose the default timeout values or set custom ones for data transmission and control operations.

MMC main feature configuration

HAL MMC advanced features configuration

The Delay Block can be configured and enabled under the advanced features section. This is recommended for high-speed MMC operation and is available on supported STM32 series. Enable the Delay Block and choose the appropriate clock phase value to optimize timing and improve data throughput.

MMC advanced feature configuration

HAL MMC security and privilege features configuration

Configure the MMC security and privilege features if needed.

MMC security and privilege feature configuration

GPIO configuration

Configure GPIO pins.

MMC GPIO configuration

NVIC configuration

Configure the NVIC in case of an interrupt.

MMC NVIC configuration

Generated MMC initialization and de-initialization sequences

The MMC initialization sequence is generated in the mx_sdmmc1_mmc_init function in mx_sdmmc1.c file under $YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.

STM32CubeMX2 Generated : MMC initialization and de-initialization sequences

Topic

HAL1 Code Snippet

HAL2 Code Snippet

Handle declaration

MMC_HandleTypeDef hmmc_card;
static hal_mmc_handle_t hMMC;

Initialization and configuration sequence

static void MX_SDMMC1_MMC_Init(void)
{
  hmmc1.Instance = SDMMC1;
  hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_FALLING;
  hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  hmmc1.Init.BusWide = SDMMC_BUS_WIDE_1B;
  hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  hmmc1.Init.ClockDiv = 0;
  if (HAL_MMC_Init(&hmmc1) != HAL_OK)
  {
    Error_Handler();
  }

}

/* HAL_MMC_MspInit callback called inside HAL_MMC_Init */
void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(hmmc->Instance==SDMMC1)
  {

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SDMMC;
    PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* Peripheral clock enable */
    __HAL_RCC_SDMMC1_CLK_ENABLE();

    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SDMMC1 GPIO Configuration
    PC4     ------> SDMMC1_CMD
    PC12     ------> SDMMC1_CK
    PB13     ------> SDMMC1_D0
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_SDMMC1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF6_SDMMC1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SDMMC1 interrupt Init */
    HAL_NVIC_SetPriority(SDMMC1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);

  }

}
hal_mmc_handle_t *mx_sdmmc1_mmc_init(void)
{
  hal_mmc_config_t mmc_config;

  if (HAL_MMC_Init(&hmmc1, HAL_MMC_CARD_1) != HAL_OK)
  {
    return NULL;
  }

  /* MMC GPIO Configuration **************************************************/

  HAL_RCC_GPIOC_EnableClock();

  HAL_RCC_GPIOB_EnableClock();

    hal_gpio_config_t  gpio_config;

  /**
    SDMMC1 GPIO Configuration

    [GPIO Pin] ------> [Signal Name]

       PC12    ------>   SDMMC1_CK
       PC4     ------>   SDMMC1_CMD
    **/
  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_11;
  HAL_GPIO_Init(HAL_GPIOC, HAL_GPIO_PIN_12 | HAL_GPIO_PIN_4, &gpio_config);

  /**
    SDMMC1 GPIO Configuration

    [GPIO Pin] ------> [Signal Name]

       PB13    ------>   SDMMC1_D0
    **/
  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_6;
  HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_13, &gpio_config);

  if (HAL_RCC_SDMMC1_SetKernelClkSource(HAL_RCC_SDMMC1_CLK_SRC_PLL) != HAL_OK)
    {
      return NULL;
    }

  HAL_RCC_SDMMC1_EnableClock();
  mmc_config.clk_cfg.clk_edge       = HAL_MMC_CLOCK_EDGE_FALLING;
  mmc_config.clk_cfg.clk_power_save = HAL_MMC_CLOCK_POWER_SAVE_DISABLE;
  mmc_config.bus_wide               = HAL_MMC_BUS_WIDE_1BIT;
  mmc_config.hw_flow_ctrl           = HAL_MMC_HARDWARE_FLOW_CONTROL_DISABLE;

  mmc_config.data_timeout_cycle     = HAL_MMC_DATA_MAX_TIMEOUT;
  mmc_config.stop_xfer_timeout_ms   = HAL_MMC_STOP_XFER_MAX_TIMEOUT;
  mmc_config.erase_timeout_ms       = HAL_MMC_ERASE_MAX_TIMEOUT;
  if (HAL_MMC_SetConfig(&hmmc1, &mmc_config) != HAL_OK)
  {
    return NULL;
  }

  if (HAL_MMC_SetFifoThreshold(&hSDMMC1,  HAL_MMC_FIFO_THRESHOLD_NOT_USED) != HAL_OK)
  {
    return NULL;
  }

  /* Enable the interruption for MMC */
  HAL_CORTEX_NVIC_SetPriority(SDMMC1_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_0, HAL_CORTEX_NVIC_SUB_PRIORITY_0);
  HAL_CORTEX_NVIC_EnableIRQ(SDMMC1_IRQn);
  return &hmmc1;
}

Deinitialization sequence

/* User should call the HAL_MMC_DeInit() function             */
/* HAL_MMC_MspDeInit is called inside HAL_MMC_DeInit function */
void HAL_MMC_MspDeInit(MMC_HandleTypeDef* hmmc)
{
  if(hmmc->Instance==SDMMC1)
  {
    /* USER CODE BEGIN SDMMC1_MspDeInit 0 */

    /* USER CODE END SDMMC1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_SDMMC1_CLK_DISABLE();

    /**SDMMC1 GPIO Configuration
    PC4      ------> SDMMC1_CMD
    PC12     ------> SDMMC1_CK
    PB13     ------> SDMMC1_D0
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_4 | GPIO_PIN_12);

    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13);

    /* SDMMC1 interrupt DeInit */
    HAL_NVIC_DisableIRQ(SDMMC1_IRQn);
    /* USER CODE BEGIN SDMMC1_MspDeInit 1 */

    /* USER CODE END SDMMC1_MspDeInit 1 */
  }

}
void mx_sdmmc1_mmc_deinit(void)
{
  (void)HAL_MMC_DeInit(&hSDMMC1);

  HAL_RCC_SDMMC1_Reset();

  HAL_RCC_SDMMC1_DisableClock();

  /* De-initialize all GPIO pins associated with SDMMC1 */
  HAL_GPIO_DeInit(HAL_GPIOC, HAL_GPIO_PIN_4 | HAL_GPIO_PIN_12);

  HAL_GPIO_DeInit(HAL_GPIOB, HAL_GPIO_PIN_13);

#if defined(USE_HAL_GPIO_HSLV) && (USE_HAL_GPIO_HSLV == 1U)
  HAL_GPIO_DisableHighSpeedLowVoltage(HAL_GPIOC, HAL_GPIO_PIN_4 | HAL_GPIO_PIN_12);
#endif /* USE_HAL_GPIO_HSLV */
#if defined(USE_HAL_GPIO_HSLV) && (USE_HAL_GPIO_HSLV == 1U)
  HAL_GPIO_DisableHighSpeedLowVoltage(HAL_GPIOB, HAL_GPIO_PIN_13);
#endif /* USE_HAL_GPIO_HSLV */
}
IRQ handle function

HAL1 / HAL2 Code Snippet

void SDMMC1_IRQHandler(void)
{
  HAL_MMC_IRQHandler(&hmmc1);
}